use crate::rtsp::rtp::utils::{Marshal, Unmarshal};
use byteorder::BigEndian;
use bytes::BytesMut;
use bytesio::bytes_errors::{BytesReadError, BytesWriteError};
use bytesio::bytes_reader::BytesReader;
use bytesio::bytes_writer::BytesWriter;

// RTP 包头
#[derive(Debug, Clone, Default)]
pub struct RtpHeader {
    // RTP 协议号
    pub version: u8,
    // 填充标志位
    pub padding_flag: u8,
    // 扩展标志位
    pub extension_flag: u8,
    // 贡献源计数器（Contributing Sources Count），占用 4 位，指示 CSRC 列表的长度
    pub cc: u8,
    // 标记位，占用 1 位，其含义由具体的应用层协议定义
    pub marker: u8,
    // 负载类型，占用 7 位，用于指示 RTP 数据包中携带的负载类型
    pub payload_type: u8,
    // 序列号，占用 16 位，用于标识 RTP 数据包的顺序
    pub seq_number: u16,
    // 时间戳，占用 32 位，用于表示 RTP 数据包中数据的采样时间
    pub timestamp: u32,
    // 同步源标识符（Synchronization Source Identifier），占用 32 位，用于唯一标识一个 RTP 会话的源
    pub ssrc: u32,
    // 贡献源标识符列表（Contributing Sources Identifiers），每个 CSRC 占用 32 位
    pub csrcs: Vec<u32>,
}

impl Unmarshal<&mut BytesReader, Result<Self, BytesReadError>> for RtpHeader {
    fn unmarshal(reader: &mut BytesReader) -> Result<Self, BytesReadError>
    where
        Self: Sized,
    {
        // 创建一个默认的 RtpHeader 实例
        let mut rtp_header = RtpHeader::default();

        // 从字节读取器中读取第一个字节
        let byte_1st: u8 = reader.read_u8()?;
        // 提取版本号，通过右移 6 位得到
        rtp_header.version = byte_1st >> 6;
        // 提取填充标志位，通过右移 5 位并与 0x01 按位与得到
        rtp_header.padding_flag = byte_1st >> 5 & 0x01;
        // 提取扩展标志位，通过右移 4 位并与 0x01 按位与得到
        rtp_header.extension_flag = byte_1st >> 4 & 0x01;
        // 提取贡献源计数器，通过与 0x0F 按位与得到
        rtp_header.cc = byte_1st & 0x0F;

        // 从字节读取器中读取第二个字节
        let byte_2nd = reader.read_u8()?;
        // 提取标记位，通过右移 7 位得到
        rtp_header.marker = byte_2nd >> 7;
        // 提取负载类型，通过与 0x7F 按位与得到
        rtp_header.payload_type = byte_2nd & 0x7F;
        // 从字节读取器中读取 16 位的序列号，使用大端字节序
        rtp_header.seq_number = reader.read_u16::<BigEndian>()?;
        // 从字节读取器中读取 32 位的时间戳，使用大端字节序
        rtp_header.timestamp = reader.read_u32::<BigEndian>()?;
        // 从字节读取器中读取 32 位的同步源标识符，使用大端字节序
        rtp_header.ssrc = reader.read_u32::<BigEndian>()?;

        // 根据贡献源计数器的值，循环读取 CSRC 列表
        for _ in 0..rtp_header.cc {
            // 从字节读取器中读取 32 位的 CSRC，使用大端字节序，并添加到 csrcs 列表中
            rtp_header.csrcs.push(reader.read_u32::<BigEndian>()?);
        }

        // 返回反序列化后的 RtpHeader 实例
        Ok(rtp_header)
    }
}

impl Marshal<Result<BytesMut, BytesWriteError>> for RtpHeader {
    // 将 RtpHeader 实例序列化为字节流的具体实现
    // RTP 头部的格式如下：
    //  0                   1                   2                   3
    //  0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
    // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
    // |V=2|P|X|  CC   |M|     PT      |       sequence number         |
    // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
    // |                           timestamp                           |
    // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
    // |           synchronization source (SSRC) identifier            |
    // +=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+
    // |            contributing source (CSRC) identifiers             |
    // |                             ....                              |
    // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
    fn marshal(&self) -> Result<BytesMut, BytesWriteError> {
        // 创建一个默认的字节写入器
        let mut writer = BytesWriter::default();

        // 构造第一个字节，将版本号左移 6 位，填充标志位左移 5 位，扩展标志位左移 4 位，
        // 贡献源计数器与 0x0F 按位与后，将这些值按位或得到第一个字节的值
        let byte_1st: u8 = (self.version << 6)
            | (self.padding_flag << 5)
            | (self.extension_flag << 4)
            | (self.cc & 0x0F);
        // 将第一个字节写入字节写入器
        writer.write_u8(byte_1st)?;

        // 构造第二个字节，将标记位左移 7 位，与负载类型按位或得到第二个字节的值
        let byte_2nd: u8 = (self.marker << 7) | self.payload_type;
        // 将第二个字节写入字节写入器
        writer.write_u8(byte_2nd)?;

        // 将 16 位的序列号写入字节写入器，使用大端字节序
        writer.write_u16::<BigEndian>(self.seq_number)?;
        // 将 32 位的时间戳写入字节写入器，使用大端字节序
        writer.write_u32::<BigEndian>(self.timestamp)?;
        // 将 32 位的同步源标识符写入字节写入器，使用大端字节序
        writer.write_u32::<BigEndian>(self.ssrc)?;

        // 遍历 CSRC 列表
        for csrc in &self.csrcs {
            // 将每个 CSRC 写入字节写入器，使用大端字节序
            writer.write_u32::<BigEndian>(*csrc)?;
        }

        // 返回序列化后的字节流
        Ok(writer.extract_current_bytes())
    }
}
